home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / Apps / DevTools / eText5 / Source / eTFileLink.subproj / eTFileLink.m < prev    next >
Encoding:
Text File  |  1995-02-04  |  7.9 KB  |  285 lines

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //    FILENAME:    eTFileLink.m
  3. //    SUMMARY:    Implementation of file components for eText documents
  4. //    SUPERCLASS:    eTImage
  5. //    INTERFACE:    None
  6. //    PROTOCOLS:    <Annotation,HTMDSupport,ASCIISupport,LaTeXSupport,Tool,
  7. //                InspectableTarget>
  8. //    AUTHOR:        Rohit Khare
  9. //    COPYRIGHT:    (c) 1994 California Institure of Technology, eText Project
  10. ///////////////////////////////////////////////////////////////////////////////
  11. //    DESCRIPTION
  12. //        Does its job by an eTComponent and execString.
  13. ///////////////////////////////////////////////////////////////////////////////
  14. //    HISTORY
  15. //    10/30/94:    Modified to support <InspectableTarget>
  16. //    08/06/94:    Added symbolic linking support.
  17. //    07/21/94:    Created. First actual implementation.
  18. ///////////////////////////////////////////////////////////////////////////////
  19.  
  20. #import "eTFileLink.h"
  21. #define _eTFileLinkPR1        10    
  22. #define _eTFileLinkVERSION    20
  23.  
  24. @implementation eTFileLink
  25. //    id        etFileComponent;
  26. //    char    *execString;
  27. //    BOOL    isExecEnabled;
  28. //    BOOL    useSymlink;
  29.  
  30. - setSymlink:(BOOL)newState
  31.     {useSymlink = newState; return self;}
  32. - setExecEnabled:(BOOL)newState
  33.     {isExecEnabled = newState; return self;}
  34. - (BOOL)useSymlink
  35.     {return useSymlink;}
  36. - (BOOL)isExecEnabled
  37.     {return isExecEnabled;}
  38. - (const char *)componentName
  39.     {return ((etFileComponent) ? [etFileComponent componentName] : NXUniqueString(""));}
  40. - (BOOL)isLinked
  41.     {return ((etFileComponent) ? [etFileComponent isLinked] : NO);}
  42. - (const char *)execString
  43.     {return execString;}
  44. - setExecString:(const char *) newString
  45. {
  46.     if (!newString) return self;
  47.     if ((!(*execString)) && *newString)
  48.         isExecEnabled = YES;
  49.     execString = realloc(execString, (strlen(newString)+1)*sizeof(char));
  50.     strcpy(execString, newString);
  51.     return self;
  52. }
  53. ////////////////////////////
  54. + toolAwake:theApp
  55. {
  56.     [theApp   registerAnnotation: [eTFileLink class] 
  57.                             name: "eTFileLink"
  58.                     RTFDirective: "eTFileLink"
  59.                        menuLabel: NULL
  60.                          menuKey: '\0'
  61.                         menuIcon: (NXImage *) nil];
  62.     [theApp registerType:NXCreateFileContentsPboardType(ANY_TYPE) for:[eTFileLink class]];
  63.     [eTRTFDFileLink toolAwake:theApp];    // "delegate chain"
  64.     return self;
  65. }
  66.  
  67. - init
  68. {
  69.     [super init];
  70.     
  71.     [self setUsesButtonStyle:NO];
  72.     [self setDraggable:YES];
  73.     isExecEnabled = NO;
  74.     useSymlink = NO;
  75.     if (!execString) {
  76.         execString = malloc(2 * sizeof(char));
  77.         execString[0] = '\0';
  78.     }
  79.     return self;
  80. }
  81.  
  82. - free 
  83. {
  84.     free(execString);
  85.     etFileComponent = [etFileComponent free];
  86.     return self = [super free];
  87. }
  88.  
  89. - _hack:sender
  90. {
  91.     // this is to prevent deadlock with the Workspace when
  92.     // requesting an icon during a dragging session
  93.     
  94.     // This is hardcoded: all FileLinks are ANY_TYPE; icons are .tiff
  95.     char imgName[MAXPATHLEN];
  96.     
  97.     sprintf(imgName,"%s.tiff",[etFileComponent componentName]);
  98.     [self setImageComponent:[[[eTImageComponent alloc] initInDoc:etDoc linked:NO] useImage:[etFileComponent icon] name:imgName path:NXUniqueString("") shared:NO]];
  99.     [self updateGraphics];
  100.     return self;
  101. }
  102. - initFromPboard:thePB inDoc:theDoc linked:(BOOL) linked
  103. {
  104.     NXAtom     types[3];
  105.     char    *data;
  106.     int        len;
  107.  
  108.     [self init];
  109.     // we prevent super from executing initFromPboard, so we have to:
  110.     etDoc = theDoc;
  111.     theText = [[etDoc docUI] eTextObj]; // consistency checking
  112.     [etDoc registerNotification:self];
  113.     
  114.     types[0] = NXCreateFileContentsPboardType(ANY_TYPE);
  115.     types[1] = NXFilenamePboardType;
  116.     types[2] = [thePB findAvailableTypeFrom:types num:2];
  117.  
  118.     if (!types[2]) return self;
  119.     if (types[2] == NXFilenamePboardType) {
  120.         [thePB readType:NXFilenamePboardType data:&data length:&len];
  121.         if (index(data,'\t')) *(index(data,'\t'))=0;
  122.         etFileComponent = [[eTComponent alloc] initInDoc:etDoc
  123.                              linked:linked];
  124.         [etFileComponent readComponentFromPath:data];
  125.         [self perform:@selector(_hack:) with:nil afterDelay:0 cancelPrevious:NO];
  126.         [thePB deallocatePasteboardData:data length:len];
  127.     } else {
  128.         NXLogError("%s got fcontents without fnamepboard! %s instead.\n",
  129.                     [[self class] name], types[2]);
  130.     }
  131.     return self;
  132. }
  133. - writeComponentToPath:(NXAtom)path inFormat:(int) theFormat
  134. {
  135.     if(!etDoc)    NXLogError("etDoc is nil at %s %u",__FILE__,__LINE__);
  136.     if (useSymlink)
  137.         [etFileComponent writeComponentToPath:path inFormat:theFormat];
  138.     else
  139.         [etFileComponent linkComponentToPath:path];
  140.     return [super writeComponentToPath:path inFormat:theFormat];
  141. }
  142. - addToPboard:pboard
  143. {
  144.     [etFileComponent addToPboard:pboard];
  145.     return self;
  146. }
  147. - readRichText:(NXStream *)stream forView:view 
  148. {
  149.     int i, ver;
  150.     char buf[MAXPATHLEN];
  151.     
  152.     NXScanf(stream, "%d ", &ver);
  153.     if ((ver != _eTFileLinkVERSION) && (ver != _eTFileLinkPR1)) {
  154.         // bad version block.
  155.         NXLogError("eTFileLink found unparseable version %d at position %d",
  156.                     ver, NXTell(stream));
  157.         return nil;
  158.     }
  159.  
  160.     NXScanf(stream, "%c ", &isExecEnabled);
  161.     isExecEnabled -= 'A';
  162.  
  163.     if (ver == _eTFileLinkVERSION) {
  164.         NXScanf(stream, "%c ", &useSymlink);
  165.         useSymlink -= 'A';
  166.     }
  167.     
  168.     NXScanf(stream, "%d", &i); NXGetc(stream); // space-eater
  169.     if (i) {
  170.         NXRead(stream, buf, i);
  171.         buf[i] = 0;
  172.         [self setExecString:buf];
  173.         NXGetc(stream); // trailing space
  174.     } // if i was zero, we have already advanced to the next non-white bit.
  175.     [super readRichText:stream forView:view];
  176.     NXGetc(stream); // separating space
  177.     etFileComponent = [[[eTComponent alloc] init] readRichText:stream forView:view];
  178.     return self;
  179. }
  180.  
  181. - writeRichText:(NXStream *)stream forView:view
  182. {    
  183.     NXPrintf(stream, "%d %c %c %d %s ", _eTFileLinkVERSION,
  184.         isExecEnabled + 'A', useSymlink + 'A', strlen(execString), execString); 
  185.     [super writeRichText:stream forView:view];
  186.     NXPutc(stream, ' ');    // separate the two visually
  187.     [etFileComponent writeRichText:stream forView:view];
  188.     return self;
  189. }
  190.  
  191. - writeASCIIRef:(NXStream *)stream forView:view
  192. {
  193.     NXPrintf(stream, "See the file %y (last known address:%s)\n\t", [etFileComponent componentName], [etFileComponent currentPath]);
  194.     [super writeASCIIRef:stream forView:view];
  195.     return self;
  196. }
  197.  
  198. - writeLaTeX:(NXStream*)stream forView:view
  199. {    
  200.     [super writeLaTeX:stream forView:view];
  201.     [etFileComponent writeLaTeX:stream forView:view 
  202.                      andClose:(*execString ? YES : NO)];
  203.     if (*execString)
  204.         NXPrintf(stream,
  205.             " Try executing the file with {\\tt %w}.}\n", execString);
  206.     return self;
  207. }
  208.  
  209. - writeHTML:(NXStream *)stream forView:view
  210. {         
  211.     [etFileComponent writeHTML:stream forView:view andClose:NO];
  212.     [super writeHTML:stream forView:view];    // icon-buttons.
  213.     if (*execString)
  214.         NXPrintf(stream,
  215.             "(execute this file with <TT>"%v"</TT>)", execString);
  216.     NXPrintf(stream,"</A>");
  217.     return self;
  218. }
  219.  
  220. - doubleClick:(NXEvent*)e
  221. {    
  222.     NXAtom fname = [etFileComponent currentPath];
  223.  
  224.     if (*fname && !access(fname, F_OK|R_OK)) {
  225.         //ok, now do we open or use execString?
  226.         if (isExecEnabled && *execString) {
  227.             char cmd[MAXPATHLEN];
  228.             id    sPanel;
  229.             
  230.             sprintf(cmd, execString, fname, fname, fname); 
  231.                     // undocumented hole: extra fnames are passed on the stack
  232.             sPanel = NXGetAlertPanel("eTFileLink",
  233.                             "Executing the command \"%s\"",
  234.                             NULL, NULL, NULL, cmd);
  235.             [sPanel setFloatingPanel:NO];
  236.             [sPanel setHideOnDeactivate:YES];
  237.             [sPanel orderFront:self];
  238.             NXPing();
  239.             system(cmd);
  240.             if (sPanel) {
  241.                 [sPanel orderOut:self];
  242.                 NXFreeAlertPanel(sPanel);
  243.             }
  244.         } else {
  245.             // we need to flip the location y coord
  246.             NXPoint pt;
  247.             NXSize    sz;
  248.             id         img;
  249.             
  250.             pt = e->location;
  251.             img = [etFileComponent icon];
  252.             [theText convertPoint:&pt fromView:nil];
  253.             [img getSize:&sz];
  254.             pt.x -= sz.width/2;
  255.             pt.y += sz.height/2;
  256.             [[Application workspace]
  257.                 openFile:fname fromImage: img
  258.                 at: &pt inView:theText];
  259.         }
  260.     } else {
  261.         if (*fname) 
  262.             NXRunAlertPanel("eTFileLink","Could not access() %s.","OK",NULL,NULL,fname);
  263.     }
  264.     return self; 
  265. }
  266.  
  267. - inspect:(NXEvent *) e
  268. {
  269.     [[NXApp inspector] inspect:self];
  270.     return self;
  271. }
  272. - (id <Inspectable>) inspectableDelegate {
  273.     return [[eTFileLinkUI new] setAnnotation:self]; }
  274.  
  275. - drag: (Pasteboard *)draggingPboard image:(NXImage **)proxyImage
  276. {
  277.     if (! etFileComponent) {
  278.         *proxyImage = nil;
  279.         return nil;
  280.     }
  281.     [etFileComponent writeComponentToPboard:draggingPboard];
  282.     *proxyImage = [etFileComponent icon];
  283.     return self;
  284. }
  285. @end